package com.example.langchain4j.utils;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONUtil;
import com.example.langchain4j.common.Result;
import com.example.langchain4j.common.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;

import java.io.BufferedInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * 通用HTTP请求工具类
 */
@Slf4j
public class HttpUtils {

    /**
     * 流式响应处理 - 适用于大文件下载或流式数据处理
     *
     * @param url           请求URL
     * @param headers       请求头
     * @param dataFunction  数据消费函数，用于处理接收到的字节数据
     * @return 响应结果
     */
    public static Result<String> streamResponse(String url, Map<String, Object> params,Map<String, String> headers,
                                         Function<byte[],String> dataFunction) {
        return streamResponse(url,params, headers, dataFunction, 8192); // 默认缓冲区大小8KB
    }

    /**
     * 流式响应处理 - 适用于大文件下载或流式数据处理
     *
     * @param url           请求URL
     * @param headers       请求头
     * @param dataFunction  数据消费函数，用于处理接收到的字节数据
     * @param bufferSize    缓冲区大小
     * @return 响应结果
     */
    public static Result<String> streamResponse(String url, Map<String, Object> params, Map<String, String> headers,
                                                Function<byte[],String> dataFunction, int bufferSize) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }

            if (dataFunction == null) {
                return Result.error(400, "数据消费函数不能为空");
            }

            HttpRequest request = HttpRequest.get(url);

            // 设置请求参数
            if (params != null && !params.isEmpty()) {
                request.form(params);
            }

            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }

            // 设置流式响应
            request.setFollowRedirects(true);

            // 执行请求并获取响应流
            HttpResponse response = request.executeAsync();

            // 获取输入流
            InputStream inputStream = response.bodyStream();
            if (inputStream == null) {
                return Result.error(500, "无法获取响应流");
            }

            // 流式读取数据
            byte[] buffer = new byte[bufferSize];
            int bytesRead;

            StringBuilder resultStr = new StringBuilder();
            try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream)) {
                while ((bytesRead = bufferedInputStream.read(buffer)) != -1) {
                    // 创建实际读取数据的字节数组
                    byte[] data = new byte[bytesRead];
                    System.arraycopy(buffer, 0, data, 0, bytesRead);

                    // 调用消费函数处理数据
                    String res = dataFunction.apply(data);
                    if (res != null && !res.isEmpty()) {
                        resultStr.append(res);
                    }
                }
            }

            // 返回成功结果
            return Result.success(resultStr.toString());

        } catch (Exception e) {
            log.error("流式响应处理异常，URL: {}", url, e);
//            return Result.error(500, "流式响应处理异常: " + e.getMessage());
            throw new BusinessException(500, "流式响应处理异常: " + e.getMessage());
        }
    }

    /**
     * 发送GET请求
     *
     * @param url     请求URL
     * @param params  请求参数
     * @param headers 请求头
     * @return 响应结果
     */
    public static Result<String> get(String url, Map<String, Object> params, Map<String, String> headers) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }
            
            HttpRequest request = HttpRequest.get(url);
            
            // 设置请求参数
            if (params != null && !params.isEmpty()) {
                request.form(params);
            }
            
            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }
            
            // 发送请求
            HttpResponse response = request.execute();
            
            // 处理响应
            return handleResponse(response);
        } catch (Exception e) {
            log.error("发送GET请求异常，URL: {}", url, e);
            return Result.error(500, "发送GET请求异常: " + e.getMessage());
        }
    }
    
    /**
     * 发送POST请求（JSON格式）
     *
     * @param url     请求URL
     * @param body    请求体（JSON对象）
     * @param headers 请求头
     * @return 响应结果
     */
    public static Result<String> postJson(String url, Object body, Map<String, String> headers) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }
            
            HttpRequest request = HttpRequest.post(url);
            
            // 设置请求体
            if (body != null) {
                String jsonBody = body instanceof String ? (String) body : JSONUtil.toJsonStr(body);
                request.body(jsonBody);
            }
            
            // 设置Content-Type为JSON
            request.contentType(ContentType.JSON.toString());
            
            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }
            
            // 发送请求
            HttpResponse response = request.execute();
            
            // 处理响应
            return handleResponse(response);
        } catch (Exception e) {
            log.error("发送POST请求异常，URL: {}", url, e);
            return Result.error(500, "发送POST请求异常: " + e.getMessage());
        }
    }
    
    /**
     * 发送POST请求（表单格式）
     *
     * @param url     请求URL
     * @param params  表单参数
     * @param headers 请求头
     * @return 响应结果
     */
    public static Result<String> postForm(String url, Map<String, Object> params, Map<String, String> headers) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }
            
            HttpRequest request = HttpRequest.post(url);
            
            // 设置表单参数
            if (params != null && !params.isEmpty()) {
                request.form(params);
            }
            
            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }
            
            // 发送请求
            HttpResponse response = request.execute();
            
            // 处理响应
            return handleResponse(response);
        } catch (Exception e) {
            log.error("发送POST表单请求异常，URL: {}", url, e);
            return Result.error(500, "发送POST表单请求异常: " + e.getMessage());
        }
    }
    
    /**
     * 发送PUT请求（JSON格式）
     *
     * @param url     请求URL
     * @param body    请求体
     * @param headers 请求头
     * @return 响应结果
     */
    public static Result<String> putJson(String url, Object body, Map<String, String> headers) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }
            
            HttpRequest request = HttpRequest.put(url);
            
            // 设置请求体
            if (body != null) {
                String jsonBody = body instanceof String ? (String) body : JSONUtil.toJsonStr(body);
                request.body(jsonBody);
            }
            
            // 设置Content-Type为JSON
            request.contentType(ContentType.JSON.toString());
            
            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }
            
            // 发送请求
            HttpResponse response = request.execute();
            
            // 处理响应
            return handleResponse(response);
        } catch (Exception e) {
            log.error("发送PUT请求异常，URL: {}", url, e);
            return Result.error(500, "发送PUT请求异常: " + e.getMessage());
        }
    }
    
    /**
     * 发送DELETE请求
     *
     * @param url     请求URL
     * @param headers 请求头
     * @return 响应结果
     */
    public static Result<String> delete(String url, Map<String, String> headers) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }
            
            HttpRequest request = HttpRequest.delete(url);
            
            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }
            
            // 发送请求
            HttpResponse response = request.execute();
            
            // 处理响应
            return handleResponse(response);
        } catch (Exception e) {
            log.error("发送DELETE请求异常，URL: {}", url, e);
            return Result.error(500, "发送DELETE请求异常: " + e.getMessage());
        }
    }
    
    /**
     * 上传文件
     *
     * @param url     请求URL
     * @param fileKey 文件字段名
     * @param file    文件路径
     * @param params  其他参数
     * @param headers 请求头
     * @return 响应结果
     */
    public static Result<String> uploadFile(String url, String fileKey, String file, 
                                   Map<String, Object> params, Map<String, String> headers) {
        try {
            if (StrUtil.isBlank(url)) {
                return Result.error(400, "请求URL不能为空");
            }
            
            if (StrUtil.isBlank(fileKey) || StrUtil.isBlank(file)) {
                return Result.error(400, "文件参数不能为空");
            }
            
            HttpRequest request = HttpRequest.post(url);
            
            // 设置文件
            request.form(fileKey, file);
            
            // 设置其他参数
            if (params != null && !params.isEmpty()) {
                params.forEach(request::form);
            }
            
            // 设置请求头
            if (headers != null && !headers.isEmpty()) {
                headers.forEach(request::header);
            }
            
            // 发送请求
            HttpResponse response = request.execute();
            
            // 处理响应
            return handleResponse(response);
        } catch (Exception e) {
            log.error("文件上传异常，URL: {}", url, e);
            return Result.error(500, "文件上传异常: " + e.getMessage());
        }
    }
    
    /**
     * 处理HTTP响应
     *
     * @param response HTTP响应
     * @return 统一响应结果
     */
    private static Result<String> handleResponse(HttpResponse response) {
        try {
            int status = response.getStatus();
            String body = response.body();
            
            log.info("HTTP请求响应状态: {}, 响应体: {}", status, body);
            
            if (status >= 200 && status < 300) {
                return Result.success(body);
            } else {
                return Result.error(status, "HTTP请求失败，状态码: " + status + "，响应体: " + body);
            }
        } catch (Exception e) {
            log.error("处理HTTP响应异常", e);
            return Result.error(500, "处理HTTP响应异常: " + e.getMessage());
        }
    }
    
    /**
     * 构建基础请求头
     *
     * @return 基础请求头Map
     */
    public static Map<String, String> buildBasicHeaders() {
        Map<String, String> headers = new HashMap<>();
        headers.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36");
        headers.put("Accept", "application/json, text/plain, */*");
        headers.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
        return headers;
    }
    
    /**
     * 添加认证头
     *
     * @param headers     请求头Map
     * @param token       认证Token
     * @param tokenPrefix Token前缀（如Bearer）
     * @return 添加认证头后的Map
     */
    public static Map<String, String> addAuthorizationHeader(Map<String, String> headers,
                                                     String token, String tokenPrefix) {
        if (headers == null) {
            headers = new HashMap<>();
        }
        
        if (StrUtil.isNotBlank(token)) {
            String prefix = StrUtil.isNotBlank(tokenPrefix) ? tokenPrefix : "Bearer";
            headers.put("Authorization", prefix + " " + token);
        }
        
        return headers;
    }
    
    /**
     * 添加JSON Content-Type头
     *
     * @param headers 请求头Map
     * @return 添加Content-Type后的Map
     */
    public static Map<String, String> addJsonContentTypeHeader(Map<String, String> headers) {
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put("Content-Type", ContentType.JSON.toString());
        return headers;
    }
}
